package net.helix.core.geometry;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL14;

import net.helix.core.Color;
import net.helix.engine.properties.Properties_Material;
import net.helix.graphics.IRenderable;

/**
 * Material class for use in a Mesh.
 * @author Runouw
 *
 */
public class Geometry_Material implements IRenderable{
	// TODO: change from texture to a LibraryItem_Image
	private Geometry_Image texKa = null;
	private Geometry_Image texKd = null;
	private Geometry_Image texKs = null;
	
	private Geometry_Image texD = null;
	
	private Color ambient;
	private Color diffuse;
	private Color specular;
	private Color emission;
	private float shininess;
	private float dissolve;
	
	public boolean useNormals = true;
	
	public Geometry_Material(){
		ambient = new Color(.2f, .2f, .2f, 1);
		diffuse = new Color(.8f, .8f, .8f, 1);
		specular = new Color(0, 0, 0, 0);
		emission = new Color(0, 0, 0, 0);
		
		dissolve = 1;
	}
	public void bind(){
		
		if(texKa != null || texKd != null || texKs != null || texKd != null){
			GL11.glEnable(GL11.GL_TEXTURE_2D);
			
			
			GL11.glEnable(GL11.GL_COLOR_MATERIAL);
			
			
			GL11.glEnable(GL11.GL_BLEND);
			GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
			
			// if use light
			GL11.glEnable(GL11.GL_LIGHTING);
			GL11.glEnable(GL11.GL_LIGHT0);
			
			GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT, ambient.getAsFloatBuffer());
			GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_DIFFUSE, diffuse.getAsFloatBuffer());
			GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_SPECULAR, specular.getAsFloatBuffer());
			GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_EMISSION, emission.getAsFloatBuffer());
			
			GL11.glMaterialf(GL11.GL_FRONT_AND_BACK, GL11.GL_SHININESS, shininess);
			
			
			// TODO: add a shader that can use textures for the ambient, diffuse and the specular.
			GL11.glColor4f(diffuse.getR(), diffuse.getR(), diffuse.getB(), dissolve);
			
			if(texKa != null){
				// ambient map
			}
			if(texKd != null){
				if(dissolve == 1){
					GL11.glEnable(GL11.GL_ALPHA_TEST);
					GL11.glAlphaFunc(GL11.GL_GREATER, 0.5f);
				}
				
				
				// diffuse map
				int textureID0 = texKd.getTexId();
				GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID0);
				
				
				
			}
			if(texKs != null){
				// specular map
			}
			
			if(texD != null){
				// alpha map
			}
			
			
			
		}else{
			// no textures on this material
			GL11.glColor4f(diffuse.getR(), diffuse.getR(), diffuse.getB(), dissolve);
		}
		
	}
	public void unbind(){
		// if uses lights
		GL11.glDisable(GL11.GL_LIGHTING);
		GL11.glDisable(GL11.GL_LIGHT0);
		
		GL11.glDisable(GL11.GL_BLEND);
				
		
		
		if(texKa != null || texKd != null || texKs != null || texKd != null){
			GL11.glDisable(GL11.GL_TEXTURE_2D);
			GL11.glDisable(GL11.GL_COLOR_MATERIAL);
		}
		
		GL11.glDisable(GL11.GL_ALPHA_TEST);
		
		
	}
	
	public void setTextureKa(Geometry_Image image){
		texKa = image;
	}
	public void setTextureKd(Geometry_Image image){
		texKd = image;
	}
	public void setTextureKs(Geometry_Image image){
		texKs = image;
	}
	public void setTextureD(Geometry_Image image){
		texD = image;
	}
	public void setAmbient(float r, float g, float b, float a){
		ambient.set(r, g, b, a);
	}
	public void setDiffuse(float r, float g, float b, float a){
		diffuse.set(r, g, b, a);
	}
	public void setSpecular(float r, float g, float b, float a){
		specular.set(r, g, b, a);
	}
	public void setEmission(float r, float g, float b, float a){
		emission.set(r, g, b, a);
	}
	public void setDissolve(float d){
		this.dissolve = d;
	}
	public void setIlluminationModel(int level){
		// TODO: set the illumination model by changing all the settings
		// it does not need to save an int for illum
	}
	// ^^^
	
	@Override
	public void render() {
		bind();
		GL11.glBegin(GL11.GL_TRIANGLES);
		GL11.glTexCoord2f(0, 0); GL11.glVertex3f(0, 0, 0);
		GL11.glTexCoord2f(1, 0); GL11.glVertex3f(1, 0, 0);
		GL11.glTexCoord2f(1, 1); GL11.glVertex3f(1, 1, 0);
		GL11.glTexCoord2f(0, 1); GL11.glVertex3f(0, 1, 0);
		GL11.glEnd();
	}
	public void applyProperties(Properties_Material properties){
		// does it do anything here?
	}
	
	
}